Skip to content

Fix DAG-level RBAC by using claim_token per UMA spec (#61137)#61283

Merged
bugraoz93 merged 5 commits intoapache:mainfrom
y-sudharshan:fix-keycloak-dag-rbac-61137
Feb 5, 2026
Merged

Fix DAG-level RBAC by using claim_token per UMA spec (#61137)#61283
bugraoz93 merged 5 commits intoapache:mainfrom
y-sudharshan:fix-keycloak-dag-rbac-61137

Conversation

@y-sudharshan
Copy link
Contributor

@y-sudharshan y-sudharshan commented Jan 31, 2026

Fix DAG-level RBAC by using claim_token per UMA specification

closes: #61137

Description

This PR fixes a bug in the Keycloak Auth Manager where context attributes (such as dag_id) were not being properly transmitted to Keycloak during authorization requests, preventing DAG-level RBAC policies from functioning.

Problem

When attempting to configure DAG-level authorization policies in Keycloak, the dag_id and other context attributes were not available to JavaScript-based policies. Network traces showed that instead of sending the actual attribute values, the literal string context=attributes was being transmitted in the authorization request.

Root Cause:
The original implementation used a non-standard context parameter with a nested dictionary:

payload["context"] = {"attributes": attributes}

This approach failed because:

  1. It is not compliant with the UMA (User-Managed Access) specification
  2. Nested dictionaries in form-urlencoded requests cannot be properly serialized by the requests library
  3. Keycloak does not recognize the context parameter for authorization requests

Solution

Implemented the correct UMA specification for pushing claims to Keycloak by using the claim_token parameter:

claims = {key: [value] for key, value in attributes.items()}
claim_json = json.dumps(claims)
claim_token = base64.b64encode(claim_json.encode()).decode()
payload["claim_token"] = claim_token
payload["claim_token_format"] = "urn:ietf:params:oauth:token-type:jwt"

Key changes:

  • Use claim_token parameter instead of context (per UMA spec)
  • Base64-encode the JSON data
  • Format claim values as arrays of strings (required by Keycloak)
  • Add claim_token_format parameter

Reference: Keycloak Authorization Services - Pushing Claims

Impact

After this fix:

  • ✅ DAG-level RBAC policies will work correctly
  • dag_id and other context attributes are accessible in Keycloak policies
  • ✅ Fine-grained authorization per DAG is now possible

Example Keycloak policy that now works:

const context = $evaluation.getContext();
const attributes = context.getAttributes();
const dagId = attributes.getValue('resource_id').asString(0);

if (dagId === 'sensitive_dag') {
    // Apply specific permissions
    $evaluation.grant();
}

Testing

  • Code passes ruff format and ruff check validation
  • Tested claim_token encoding/decoding with validation script
  • Verified form-urlencoded transmission preserves data correctly
  • Confirmed backwards compatibility (no impact when attributes are not provided)

Changes Made

Modified files:

  1. providers/keycloak/src/airflow/providers/keycloak/auth_manager/keycloak_auth_manager.py
       - Added import base64
       - Updated _get_payload() method to use claim_token parameter

  2. providers/keycloak/docs/changelog.rst
       - Added bug fix entry for version 0.5.2


Was generative AI tooling used to co-author this PR?
  • Yes (please specify the tool below)

Generated-by: GitHub Copilot

Copy link

@n-badtke-cg n-badtke-cg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ddroessler-ext
Copy link

I tested the changes locally and can confirm that it works as expected - thanks a lot for the quick implementation.
The dag id is correctly sent to Keycloak and also available in JavaScript policies.

Small nit on your example in the PR, the id of the requested dag is in key resource_id instead of dag_id.

Copy link
Contributor

@vincbeck vincbeck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing that issue. I added some comments, also, can you update/create test to cover that?

Ensure consistent JSON key ordering by using sort_keys=True in json.dumps()
when generating claim_token for UMA ticket requests. This fixes test failures
caused by non-deterministic dictionary ordering in Python.

The claim_token is base64-encoded JSON, so consistent key ordering is required
for test assertions and predictable behavior.
- Fix documentation URL anchor from #_service_authorization_pushing_claims to #_service_pushing_claims
- Remove changelog entry as requested by release manager
- Add comprehensive parametrized tests for _get_payload method covering claim_token functionality
@y-sudharshan y-sudharshan force-pushed the fix-keycloak-dag-rbac-61137 branch from 3ce9b7c to 522ef10 Compare February 2, 2026 16:31
Copy link
Contributor

@bugraoz93 bugraoz93 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still a quite bit of CI failing. Could you please check?

@y-sudharshan y-sudharshan force-pushed the fix-keycloak-dag-rbac-61137 branch from 8c7cb34 to d71e45e Compare February 3, 2026 01:55
@y-sudharshan y-sudharshan requested a review from vincbeck February 5, 2026 05:07
@vincbeck vincbeck requested a review from bugraoz93 February 5, 2026 15:14
@bugraoz93 bugraoz93 merged commit 598eff4 into apache:main Feb 5, 2026
86 checks passed
@n-badtke-cg
Copy link

🥳

jhgoebbert pushed a commit to jhgoebbert/airflow_Owen-CH-Leung that referenced this pull request Feb 8, 2026
* Fix DAG-level RBAC by using claim_token per UMA spec (apache#61137)

* Fix claim_token ordering in Keycloak auth manager

Ensure consistent JSON key ordering by using sort_keys=True in json.dumps()
when generating claim_token for UMA ticket requests. This fixes test failures
caused by non-deterministic dictionary ordering in Python.

The claim_token is base64-encoded JSON, so consistent key ordering is required
for test assertions and predictable behavior.

* Address review comments: fix doc URL, remove changelog, add tests

- Fix documentation URL anchor from #_service_authorization_pushing_claims to #_service_pushing_claims
- Remove changelog entry as requested by release manager
- Add comprehensive parametrized tests for _get_payload method covering claim_token functionality
@y-sudharshan
Copy link
Contributor Author

🥳

Thanks!
Thanks for your relevant and quick review

Ratasa143 pushed a commit to Ratasa143/airflow that referenced this pull request Feb 15, 2026
* Fix DAG-level RBAC by using claim_token per UMA spec (apache#61137)

* Fix claim_token ordering in Keycloak auth manager

Ensure consistent JSON key ordering by using sort_keys=True in json.dumps()
when generating claim_token for UMA ticket requests. This fixes test failures
caused by non-deterministic dictionary ordering in Python.

The claim_token is base64-encoded JSON, so consistent key ordering is required
for test assertions and predictable behavior.

* Address review comments: fix doc URL, remove changelog, add tests

- Fix documentation URL anchor from #_service_authorization_pushing_claims to #_service_pushing_claims
- Remove changelog entry as requested by release manager
- Add comprehensive parametrized tests for _get_payload method covering claim_token functionality
choo121600 pushed a commit to choo121600/airflow that referenced this pull request Feb 22, 2026
* Fix DAG-level RBAC by using claim_token per UMA spec (apache#61137)

* Fix claim_token ordering in Keycloak auth manager

Ensure consistent JSON key ordering by using sort_keys=True in json.dumps()
when generating claim_token for UMA ticket requests. This fixes test failures
caused by non-deterministic dictionary ordering in Python.

The claim_token is base64-encoded JSON, so consistent key ordering is required
for test assertions and predictable behavior.

* Address review comments: fix doc URL, remove changelog, add tests

- Fix documentation URL anchor from #_service_authorization_pushing_claims to #_service_pushing_claims
- Remove changelog entry as requested by release manager
- Add comprehensive parametrized tests for _get_payload method covering claim_token functionality
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to configure DAG-level RBAC with Keycloak Auth Manager: Missing dag_id in context

5 participants